package com.ctrip.framework.apollo.portal.spi.ctrip;

import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.component.config.PortalConfig;
import com.ctrip.framework.apollo.portal.entity.bo.ReleaseHistoryBO;
import com.ctrip.framework.apollo.portal.service.AppService;
import com.ctrip.framework.apollo.portal.service.ReleaseService;
import com.ctrip.framework.apollo.portal.spi.MQService;
import com.ctrip.framework.apollo.tracer.Tracer;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import java.util.Arrays;


public class CtripMQService implements MQService {

    private static final org.apache.commons.lang.time.FastDateFormat
            TIMESTAMP_FORMAT = org.apache.commons.lang.time.FastDateFormat.getInstance("yyyy-MM-dd hh:mm:ss");
    private static final String CONFIG_PUBLISH_NOTIFY_TO_NOC_TOPIC = "ops.noc.record.created";

    private Gson gson = new Gson();

    @Autowired
    private AppService appService;
    @Autowired
    private ReleaseService releaseService;
    @Autowired
    private PortalConfig portalConfig;

    private RestTemplate restTemplate;

    @PostConstruct
    public void init() {
        restTemplate = new RestTemplate();

        SimpleClientHttpRequestFactory rf = (SimpleClientHttpRequestFactory) restTemplate.getRequestFactory();
        rf.setReadTimeout(portalConfig.readTimeout());
        rf.setConnectTimeout(portalConfig.connectTimeout());

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setSupportedMediaTypes(
                Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM));

        restTemplate.setMessageConverters(Arrays.asList(converter, new FormHttpMessageConverter()));

    }

    @Override
    public void sendPublishMsg(Env env, ReleaseHistoryBO releaseHistory) {
        if (releaseHistory == null) {
            return;
        }

        PublishMsg msg = buildPublishMsg(env, releaseHistory);

        sendMsg(portalConfig.hermesServerAddress(), CONFIG_PUBLISH_NOTIFY_TO_NOC_TOPIC, msg);
    }

    private PublishMsg buildPublishMsg(Env env, ReleaseHistoryBO releaseHistory) {

        PublishMsg msg = new PublishMsg();

        msg.setPriority("中");
        msg.setTool_origin("Apollo");

        String appId = releaseHistory.getAppId();
        App app = appService.load(appId);
        msg.setInfluence_bu(app.getOrgName());
        msg.setAppid(appId);
        msg.setAssginee(releaseHistory.getOperator());
        msg.setOperation_time(TIMESTAMP_FORMAT.format(releaseHistory.getReleaseTime()));
        msg.setDesc(gson.toJson(releaseService.compare(env, releaseHistory.getPreviousReleaseId(),
                releaseHistory.getReleaseId())));

        return msg;
    }

    private void sendMsg(String serverAddress, String topic, Object msg) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_OCTET_STREAM + ";charset=UTF-8"));
        HttpEntity<Object> request = new HttpEntity<>(msg, headers);

        try {
            //send msg by hermes RestAPI
            restTemplate.postForObject(serverAddress + "/topics/" + topic, request, Object.class);

        } catch (Exception e) {
            Tracer.logError("Send publish msg to hermes failed", e);
        }

    }

    private class PublishMsg {

        private String assginee;
        private String desc;
        private String operation_time;
        private String tool_origin;
        private String priority;
        private String influence_bu;
        private String appid;


        public String getAssginee() {
            return assginee;
        }

        public void setAssginee(String assginee) {
            this.assginee = assginee;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        public String getOperation_time() {
            return operation_time;
        }

        public void setOperation_time(String operation_time) {
            this.operation_time = operation_time;
        }

        public String getTool_origin() {
            return tool_origin;
        }

        public void setTool_origin(String tool_origin) {
            this.tool_origin = tool_origin;
        }

        public String getPriority() {
            return priority;
        }

        public void setPriority(String priority) {
            this.priority = priority;
        }

        public String getInfluence_bu() {
            return influence_bu;
        }

        public void setInfluence_bu(String influence_bu) {
            this.influence_bu = influence_bu;
        }

        public String getAppid() {
            return appid;
        }

        public void setAppid(String appid) {
            this.appid = appid;
        }
    }

}
